package com.liqiye.paymanager.service.payment;

import com.liqiye.paymanager.bean.payment.*;
import com.liqiye.paymanager.constant.PaymentStatus;
import com.liqiye.paymanager.util.PayPalClientUtil;
import com.paypal.http.HttpRequest;
import com.paypal.http.HttpResponse;
import com.paypal.orders.*;
import com.paypal.payments.CapturesRefundRequest;
import com.paypal.payments.Refund;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class PayPalPaymentService implements PaymentService {

    private final PayPalClientUtil payPalClientUtil;

    public PayPalPaymentService(PayPalClientUtil payPalClientUtil) {
        this.payPalClientUtil = payPalClientUtil;
    }

    /**
     * 在 PayPal 中，是创建一个 order
     */
    @Override
    public PaymentResponse createPayment(PaymentRequest req) {
        PaymentResponse resp = new PaymentResponse();
        OrderRequest orderRequest = new OrderRequest()
                .checkoutPaymentIntent("CAPTURE")
                .purchaseUnits(List.of(
                        new PurchaseUnitRequest()
                                .amountWithBreakdown(
                                        new AmountWithBreakdown()
                                                .currencyCode(req.getCurrency())
                                                .value(req.getAmount().toString())
                                )
                                .description(req.getDescription())
                ));

        OrdersCreateRequest request = new OrdersCreateRequest().requestBody(orderRequest);

        try {
            HttpResponse<Order> response = payPalClientUtil.getClient().execute(request);
            Order order = response.result();
            resp.success = true;
            resp.platformOrderId = order.id();
            String paymentUrl = order.links().stream()
                    .filter(l -> "approve".equals(l.rel()))
                    .findFirst()
                    .map(LinkDescription::href)
                    .orElse(null);
            resp.paymentUrl = paymentUrl;
        } catch (IOException e) {
            e.printStackTrace();
            resp.success = false;
            resp.message = e.getMessage();
        }

        return resp;
    }

    public CaptureResponse captureOrder(String orderId) {
        CaptureResponse resp = new CaptureResponse();
        HttpRequest<Order> request = new OrdersCaptureRequest(orderId)
                .requestBody(new OrderRequest()); //  body empty

        try {
            HttpResponse<Order> response = payPalClientUtil.getClient().execute(request);
            Order order = response.result();
            String captureId = null;
            for (PurchaseUnit purchaseUnit : order.purchaseUnits()) {
                if (purchaseUnit.payments() != null && purchaseUnit.payments().captures() != null) {
                    for (Capture capture : purchaseUnit.payments().captures()) {
                        captureId = capture.id();
                    }
                }
            }
            resp.captureId = captureId;
            resp.success = true;
            resp.platformOrderId = order.id();
            resp.status = "COMPLETED".equalsIgnoreCase(order.status())
                    ? PaymentStatus.SUCCESS : PaymentStatus.FAILED;
            resp.rawStatus = order.status();
        } catch (IOException e) {
            resp.success = false;
            resp.message = e.getMessage();
        }
        return resp;
    }

    @Override
    public PaymentStatusResponse queryPayment(String platformOrderId) {

        return null;
    }

    @Override
    public RefundResponse refund(RefundRequest refundRequest) {
        CapturesRefundRequest request = new CapturesRefundRequest(refundRequest.getCaptureId());

        Map<String, Object> body = new HashMap<>();
        if(refundRequest.getCurrency() != null && refundRequest.getAmount() != null) {
            Money money = new Money()
                    .currencyCode(refundRequest.getCurrency())
                    .value(refundRequest.getAmount().toPlainString());
            body.put("amount", money);
        }
        request.requestBody(body);

        RefundResponse refundResponse = new RefundResponse();
        try {
            HttpResponse<Refund> response = payPalClientUtil.getClient().execute(request);
            Refund refund = response.result();

            refundResponse.success = true;
            refundResponse.refundId = refund.id();
            if(refund.amount() != null){
                refundResponse.refundedAmount = refund.amount().value();
                refundResponse.refundCurrency = refund.amount().currencyCode();
            }
            refundResponse.status = refund.status();
            refundResponse.captureId = refundRequest.captureId;
            refundResponse.message = "Refund success";
            return refundResponse;

        } catch (IOException e) {

            e.printStackTrace();
            refundResponse.success = false;
            if(refundRequest.amount != null) {
                refundResponse.refundedAmount = refundRequest.amount.toString();
            }
            refundResponse.refundCurrency = refundRequest.currency;
            refundResponse.captureId = refundRequest.captureId;
            refundResponse.message = "Refund failed: " + e.getMessage();
            return refundResponse;
        }

    }

    @Override
    public CallbackResponse handleCallback(String payload, String signature) {

        return null;
    }

}
